home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_unix / j109lxa4.tar / bootpcmd.c < prev    next >
C/C++ Source or Header  |  1994-06-04  |  15KB  |  712 lines

  1. /*************************************************/
  2. /* Center for Information Technology Integration */
  3. /*           The University of Michigan          */
  4. /*                    Ann Arbor                  */
  5. /*                                               */
  6. /* Dedicated to the public domain.               */
  7. /* Send questions to info@citi.umich.edu         */
  8. /*                                               */
  9. /* BOOTP is documented in RFC 951 and RFC 1048   */
  10. /*************************************************/
  11.  
  12.  
  13.  
  14. #include <stdio.h>
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #include <time.h>
  18. #include <ctype.h>
  19. #ifdef  ANSIPROTO
  20. #include <stdarg.h>
  21. #endif
  22. #include "global.h"
  23. #include "config.h"
  24. #include "cmdparse.h"
  25. #include "bootpd.h"
  26. #include "netuser.h"
  27. #include "iface.h"
  28. #include "udp.h"
  29. #include "arp.h"
  30.  
  31. #define BP_DEFAULT_TAB "bootptab"
  32. #define BP_DEFAULT_LOG "bootplog"
  33. #define BP_DEFAULT_DIR "bpfiles"
  34. #define BP_DEFAULT_FILE "boot"
  35.  
  36. static char    *bootptab = BP_DEFAULT_TAB;
  37. static FILE    *bootfp;                 /* bootptab fp */
  38. static long     modtime;                /* last modification time of bootptab */
  39.  
  40. static char    bootplog[64] = BP_DEFAULT_LOG;
  41. static int      LogInFile = 0;          /* Should bp_log log in a file? */
  42. static int      LogOnScreen = 0;        /* Should bp_log log on screen? */
  43.  
  44. static char    *line;            /* line buffer for reading bootptab */
  45. static int     linenum;          /* current ilne number in bootptab */
  46.  
  47. extern int      Nhosts;          /* number of hosts in host structure */
  48. extern struct host hosts[MHOSTS+1];
  49.  
  50. extern char    homedir[64];      /* bootfile homedirectory */
  51. extern char    defaultboot[64];  /* default file to boot */
  52. extern int32   bp_DefaultDomainNS[BP_MAXDNS]; /* default domain name server */
  53. extern int      Nhosts;
  54. extern struct udp_cb *Bootpd_cb;
  55.  
  56.  
  57.  
  58.  
  59.  
  60. static int bp_Homedir           __ARGS((int argc,char *argv[],void *p));
  61. static int bp_DefaultFile       __ARGS((int argc,char *argv[],void *p));
  62. static int bp_DynamicRange      __ARGS((int argc,char *argv[],void *p));
  63. static int bp_donothing         __ARGS((int argc,char *argv[],void *p));
  64. static int bp_Host              __ARGS((int argc,char *argv[],void *p));
  65. static int bp_rmHost            __ARGS((int argc,char *argv[],void *p));
  66. static int bp_DomainNS          __ARGS((int argc,char *argv[],void *p));
  67. static int bp_Start             __ARGS((int argc,char *argv[],void *p));
  68. static int bp_Stop              __ARGS((int argc,char *argv[],void *p));
  69. static int bp_logFile           __ARGS((int argc,char *argv[],void *p));
  70. static int bp_logScreen                 __ARGS((int argc,char *argv[],void *p));
  71. static void  dumphosts          __ARGS((void));
  72.  
  73.  
  74. void bootpd __ARGS((struct iface *iface, struct udp_cb *sock, int cnt));
  75.  
  76. static struct cmds BootpdCmds[] = {
  77.     "",             bp_donothing,           0, 0, NULLCHAR,
  78.     "start",        bp_Start,               0, 0, NULLCHAR,
  79.     "stop",         bp_Stop,                0, 0, NULLCHAR,
  80.     "dns",          bp_DomainNS,            0, 0, NULLCHAR,
  81.     "dynip",        bp_DynamicRange,        0, 0, NULLCHAR,
  82.     "host",         bp_Host,                0, 0, NULLCHAR,
  83.     "rmhost",       bp_rmHost,              0, 0, NULLCHAR,
  84.     "homedir",      bp_Homedir,             0, 0, NULLCHAR,
  85.     "defaultfile",  bp_DefaultFile,         0, 0, NULLCHAR,
  86.     "logfile",      bp_logFile,             0, 0, NULLCHAR,
  87.     "logscreen",    bp_logScreen,           0, 0, NULLCHAR,
  88.     NULLCHAR,       NULLFP((int,char**,void*)), 0, 0, NULLCHAR
  89. };
  90.  
  91.  
  92.  
  93. int 
  94. #ifdef PROTOTYPES
  95. bootpdcmd (int argc, char **argv, void *p)
  96. #else
  97. bootpdcmd (argc, argv, p)
  98. int argc;
  99. char *argv[];
  100. void *p;
  101. #endif
  102. {
  103.     return subcmd (BootpdCmds, argc, argv, p);
  104. }
  105.  
  106.  
  107. /* Start up bootp service */
  108. static int
  109. bp_Start (argc,argv,p)
  110. int argc;
  111. char *argv[];
  112. void *p;
  113. {
  114.  
  115.     struct socket lsock;
  116.     time_t tloc;
  117.     char *usage = "bootpd start\n";
  118.  
  119.     if (argc != 1) {
  120.         tprintf (usage);
  121.         return (-1);
  122.     }
  123.  
  124.     time(&tloc);
  125.     bp_log ("\n\n####BOOTP server starting at %s\n", ctime(&tloc));
  126.  
  127.     lsock.address = INADDR_ANY;
  128.     lsock.port = IPPORT_BOOTPS;
  129.  
  130.     /* This way is better than recvfrom because it passes the iface in bootpd call */
  131.        /* Listen doesn't work for datagrams. */
  132.  
  133.     if (Bootpd_cb == NULLUDP) {
  134.         if ((Bootpd_cb = open_udp(&lsock, bootpd)) == NULLUDP) {
  135.             tprintf ("bootpd: can't open_udp\n");   
  136.             return (-1);
  137.         }
  138.     }
  139.  
  140.     /*
  141.      * Read the bootptab file once immediately upon startup.
  142.      */
  143.  
  144.     da_init();
  145.  
  146.     readtab();
  147.  
  148.     return (0);
  149. }
  150.  
  151.  
  152.  
  153. /* Stop bootp service */
  154. static int
  155. bp_Stop (argc, argv, p)
  156. int argc;
  157. char *argv[];
  158. void *p;
  159. {
  160.     time_t now;
  161.     char *usage = "bootpd stop\n";
  162.  
  163.     if (argc != 1) {
  164.         tprintf (usage);
  165.         return -1;
  166.     }
  167.  
  168.     time (&now);
  169.  
  170.     Nhosts = 0;
  171.     da_shut();
  172.     readtab_shut();
  173.     del_udp (Bootpd_cb);
  174.     Bootpd_cb = NULLUDP;
  175.  
  176.     bp_log ("Bootpd shutdown %s", ctime (&now));
  177.     return (0);
  178. };
  179.  
  180.  
  181.  
  182. static int
  183. bp_logFile (argc, argv, p)
  184. int argc;
  185. char *argv[];
  186. void *p;
  187. {
  188.     int i;
  189.     time_t now;
  190.     char *usage = "bootpd logfile [<file_name> | default] [on | off] \n"; 
  191.  
  192.     time (&now);
  193.  
  194.     if (argc == 1) {
  195.         if (LogInFile)
  196.             tprintf ("Bootpd logging to file '%s' turned on.\n", bootplog);
  197.         else 
  198.             tprintf ("Bootpd logging to file '%s' turned off.\n", bootplog);
  199.     }
  200.     else {
  201.         for (i = 1; i < argc; i++) {
  202.  
  203.             if (strcmp ("?", argv[i]) == 0) 
  204.                 tprintf (usage);
  205.  
  206.             else if (strcmp ("off", argv[i]) == 0) {
  207.                 bp_log ("Stopping file logging at %s", ctime(&now));
  208.                 LogInFile = 0;
  209.             }
  210.             else if (strcmp ("on", argv[i]) == 0) {
  211.                 LogInFile = 1;
  212.                 bp_log ("Starting file logging at %s", ctime(&now));
  213.             }
  214.             else if (strcmp ("default", argv[i]) == 0) {
  215.                 strcpy (bootplog, BP_DEFAULT_LOG);
  216.                 bp_log ("File for logging set to %s\n", bootplog);
  217.             }
  218.             else {
  219.                 strcpy (bootplog, argv[1]);
  220.                 bp_log ("File for logging set to %s\n", bootplog);
  221.             }       
  222.         }
  223.     }
  224.     return 0;
  225. }
  226.  
  227.  
  228. static int
  229. bp_logScreen (argc, argv, p)
  230. int argc;
  231. char *argv[];
  232. void *p;
  233. {
  234.     char *usage = "bootpd logscreen [on | off]\n";  
  235.  
  236.     if (argc == 1)
  237.         if (LogOnScreen)        
  238.             tprintf ("Bootpd logging on screen turned on.\n");
  239.         else 
  240.             tprintf ("Bootpd logging on screen turned off.\n");
  241.  
  242.     else if (argc == 2)  {
  243.         if  (strcmp ("on", argv[1]) == 0)
  244.             LogOnScreen = 1;
  245.         else if  (strcmp ("off", argv[1]) == 0)
  246.             LogOnScreen = 0;
  247.         else tprintf (usage);
  248.     }
  249.     else tprintf (usage);
  250.     return 0;
  251. }
  252.  
  253.  
  254.  
  255.  
  256. static int
  257. bp_DomainNS (argc, argv, p)
  258. int argc;
  259. char *argv[];
  260. void *p;
  261. {
  262.     int a0, a1, a2, a3;
  263.     int i;
  264.     char *usage = "bootpd dns [<IP addr of domain name server>...]\n";
  265.  
  266.     if (argc == 1) {
  267.         tprintf ("Bootp domain name servers: ");
  268.         for (i=0; (i < BP_MAXDNS) && (bp_DefaultDomainNS[i] != 0); i++) 
  269.             tprintf (" %s", inet_ntoa (bp_DefaultDomainNS[i]));
  270.         tprintf ("\n");
  271.         return (0);
  272.     }
  273.  
  274.     if (argc > 1) {
  275.         if ((argc == 2) && (strcmp ("?", argv[1]) == 0)) {
  276.             tprintf (usage);
  277.             return 0;
  278.         }
  279.             
  280.         /* A list of name servers has been given */
  281.         /* reset the domain name server list */
  282.         for (i= 0; i < BP_MAXDNS; i++) 
  283.             bp_DefaultDomainNS[i] = 0;
  284.  
  285.         /* get ip address */
  286.         for (i = 1; (i < argc) && (i < BP_MAXDNS); i++) {
  287.             if (4 != sscanf (argv[i], "%d.%d.%d.%d", &a0, &a1, &a2, &a3)) {
  288.                 tprintf("bad internet address: %s\n", argv[1] /*, linenum*/);
  289.                 return  -1;
  290.             }
  291.             bp_DefaultDomainNS[i-1] = aton(argv[i]);
  292.         }
  293.     }
  294.     /* record for the loggers sake */
  295.     bp_log ("Bootp domain name servers: ");
  296.     for (i=0; (i < BP_MAXDNS) && (bp_DefaultDomainNS[i] != 0); i++) 
  297.         bp_log (" %s", inet_ntoa (bp_DefaultDomainNS[i]));
  298.     bp_log ("\n");
  299.     return 0;
  300. }
  301.  
  302.  
  303.  
  304. static int
  305. bp_rmHost (argc, argv, p)
  306. int argc;
  307. char *argv[];
  308. void *p;
  309. {
  310.     int i;
  311.     struct host *hp = NULLHOST;
  312.     struct host *cp = NULLHOST;
  313.     char *usage = "bootpd rmhost <host name>\n";
  314.  
  315.  
  316.     if (argc == 2) {
  317.         
  318.         /* Find the host record */
  319.         for (i=0; i < Nhosts; i++) {
  320.             if (strcmp (hosts[i].name, argv[1]) == 0) {
  321.                 hp = &(hosts[i]);
  322.                 break;
  323.             }
  324.         }       
  325.         /* Return if not found */
  326.         if (hp == NULLHOST) {
  327.             tprintf ("Host %s not in host tables.\n", argv[1]);
  328.             return -1;
  329.         }
  330.         bp_log ("Host %s removed from host table\n", hp->name);
  331.         cp = &(hosts [Nhosts - 1]);
  332.         if (hp < cp) 
  333.             memcpy ((char *) hp, (char *) cp, sizeof (struct host));
  334.         Nhosts--;
  335.         return 0;
  336.     }
  337.     else tprintf (usage);
  338.     return 0;
  339. }
  340.  
  341.  
  342. /*
  343.  * Printout the hosts table.
  344. */
  345. static void
  346. dumphosts()
  347. {
  348.     int i;
  349.     struct host *hp;
  350.     struct arp_type *at;
  351.  
  352.     tprintf ("\n\nStatus of host table\n");
  353.  
  354.     if (Nhosts == 0) {
  355.         tprintf ("     No hosts in host table\n");
  356.         return;
  357.     }
  358.     for (i = 0; i <= Nhosts-1; i++) {
  359.         hp = &hosts[i];
  360.         at = &Arp_type[hp->htype];
  361.         
  362.         tprintf ("%s  %s  %s  %s  '%s'\n",
  363.             hp->name, ArpNames[hp->htype], (*at->format)(bp_ascii, hp->haddr),
  364.             inet_ntoa ((int32)hp->iaddr.s_addr),
  365.             hp->bootfile);
  366.  
  367.     }
  368. }
  369.  
  370.  
  371. static int
  372. bp_Host (argc, argv, p)
  373. int argc;
  374. char *argv[];
  375. void *p;
  376. {
  377.     struct host *hp;
  378.     int a0, a1, a2, a3;
  379.     struct arp_type *at;
  380.     char *usage = "bootpd host [<hostname> <hardware type> <hardware addr> <ip addr> [boot file]]\n";
  381.  
  382.     switch (argc) {
  383.     case 1: 
  384.         dumphosts();
  385.         break;
  386.     case 5:
  387.     case 6:
  388.     
  389.         hp = &hosts[Nhosts];
  390.         
  391.         /* get host name */
  392.         strncpy (hp->name, argv[1], sizeof (hp->name));
  393.  
  394.         /* get hardware type */
  395.         /* This code borrowed from Phil Karn's arpcmd.c */
  396.         /* This is a kludge. It really ought to be table driven */
  397.         switch(tolower(argv[2][0])){
  398.             case 'n':       /* Net/Rom pseudo-type */
  399.                 hp->htype = ARP_NETROM;
  400.                 break;
  401.             case 'e': /* "ether" */
  402.                 hp->htype = ARP_ETHER;
  403.                 break;
  404.             case 'a': /* "ax25" */
  405.                 hp->htype = ARP_AX25;
  406.                 break;
  407.             case 'm': /* "mac appletalk" */
  408.                 hp->htype = ARP_APPLETALK;
  409.                 break;
  410.             default:
  411.                 tprintf("unknown hardware type \"%s\"\n",argv[2]);
  412.                 return -1;
  413.         }
  414.  
  415.         at = &Arp_type[hp->htype];
  416.         if(at->scan == NULLFP((char*,char*))){
  417.             return 1;
  418.         }
  419.         /* Destination address */
  420.         (*at->scan)(hp->haddr,argv[3]);
  421.  
  422.  
  423.         /* get ip address */
  424.         if (4 != sscanf (argv[4], "%d.%d.%d.%d", &a0, &a1, &a2, &a3))
  425.         {
  426.             tprintf("bad internet address: %s\n", argv[1] /*, linenum*/);
  427.             return (0);
  428.         }
  429.         hp->iaddr.s_addr = aton(argv[4]);
  430.  
  431.         /* get the bootpfile */
  432.         if (argc == 6) strncpy (hp->bootfile, argv[5], sizeof (hp->bootfile));
  433.         else hp->bootfile[0] = 0;
  434.  
  435.         bp_log ("Host added: %s  %s  %s  %s  '%s'\n",
  436.             hp->name, ArpNames[hp->htype], (*at->format)(bp_ascii, hp->haddr),
  437.             inet_ntoa ((int32)hp->iaddr.s_addr),
  438.             hp->bootfile);
  439.  
  440.  
  441.         Nhosts++;
  442.         break;
  443.     
  444.     default:
  445.         tprintf (usage);
  446.         break;
  447.     }
  448.     return 0;
  449. }
  450.  
  451.  
  452.  
  453. static int      
  454. bp_Homedir (argc, argv, p)
  455. int argc;
  456. char *argv[];
  457. void *p;
  458. {
  459.     char *usage = "bootpd homedir [<name of home directory> | default]\n";
  460.  
  461.     if (argc == 1)  
  462.         tprintf ("Bootp home directory: '%s'\n", homedir);
  463.     else if (argc == 2) {
  464.         if (strcmp (argv[1], "?") == 0)
  465.             tprintf (usage);
  466.         else if (strcmp (argv[1], "default") == 0) {
  467.             strcpy (homedir, BP_DEFAULT_DIR);
  468.             bp_log ("Bootp home directory set to: '%s'\n", homedir);
  469.         }
  470.         else {
  471.             strcpy (homedir, argv[1]);
  472.             bp_log ("Bootp home directory set to: '%s'\n", homedir);
  473.         }
  474.     }
  475.     else tprintf (usage);
  476.     return (0);
  477. };
  478.  
  479.  
  480.  
  481. static int
  482. bp_DefaultFile (argc, argv, p)
  483. int argc;
  484. char *argv[];
  485. void *p;
  486. {
  487.     char *usage = "bootpd defaultfile [<name of default boot file> | default]\n";
  488.  
  489.     if (argc == 1)
  490.         tprintf ("Bootp default boot file:  '%s'\n", defaultboot);
  491.     else if (argc == 2) {
  492.         if (strcmp (argv[1], "?") == 0)
  493.             tprintf (usage);
  494.         else if (strcmp (argv[1], "default") == 0)
  495.             strcpy (defaultboot, BP_DEFAULT_FILE);
  496.         else {
  497.             strcpy (defaultboot, argv[1]);
  498.             bp_log ("Bootp default boot file set to:  '%s'\n", defaultboot);
  499.         }
  500.     }
  501.     else
  502.         tprintf (usage);
  503.  
  504.     return  (0);
  505. };
  506.  
  507.  
  508. static int
  509. bp_DynamicRange (argc, argv, p)
  510. int argc;
  511. char *argv[];
  512. void *p;
  513. {
  514.     int i0, i1, i2, i3;
  515.     int32 start, end;
  516.     struct iface *iface;
  517.     char *usage = "bootpd dynip [<net name> | <netname>  <IP address> <IP address> | <netname> off]\n";
  518.  
  519.     if (argc == 1) {
  520.         da_status (NULLIF);
  521.         return 0;
  522.     }
  523.     if ((argc == 2) && (strcmp ("?", argv[1]) == 0)) {
  524.             tprintf (usage);
  525.             return 0;
  526.     }
  527.  
  528.     /* get the interface */
  529.     iface = if_lookup (argv[1]);
  530.     if (iface == NULLIF) {
  531.         tprintf ("network '%s' not found\n", argv[1]);
  532.         return  (-1);
  533.     }
  534.     if (argc == 2) {
  535.         da_status (iface);
  536.         return 0;
  537.     }
  538.     if (argc == 3) {
  539.         if (strcmp ("off", argv[2]) == 0) 
  540.             da_done_net (iface);
  541.         else tprintf (usage);
  542.     }
  543.     else if (argc == 4) {
  544.         
  545.         /* get ip address */
  546.         /* check the ip address - isaddr isn't a ka9q function */
  547.         if ((4 != sscanf (argv[2], "%d.%d.%d.%d", &i0, &i1, &i2, &i3)) || 
  548.             (i0 > 255) || (i1 > 255) || (i2 > 255) || (i3 > 255)
  549.         )
  550.         {
  551.             tprintf("bad internet address: %s\n", argv[2] /*, linenum*/);
  552.             return (-1);
  553.         }
  554.  
  555.         if ((4 != sscanf (argv[3], "%d.%d.%d.%d", &i0, &i1, &i2, &i3)) || 
  556.             (i0 > 255) || (i1 > 255) || (i2 > 255) || (i3 > 255)
  557.         )
  558.         {
  559.             tprintf("bad internet address: %s\n", argv[3] /*, linenum*/);
  560.             return (-1);
  561.         }
  562.  
  563.         start = aton(argv[2]);
  564.         end = aton(argv[3]);
  565.  
  566.         da_serve_net (iface, start, end);
  567.  
  568.     }
  569.     else {
  570.         tprintf (usage);
  571.         return (0);
  572.     }
  573.  
  574.     return (0);
  575. };
  576.  
  577.  
  578. static int
  579. bp_donothing (argc, argv, p)
  580. int argc;
  581. char *argv[];
  582. void *p;
  583. {
  584.     return (0);
  585. }
  586.  
  587.  
  588. /*
  589.  * Read bootptab database file.  Avoid rereading the file if the
  590.  * write date hasn't changed since the last time we read it.
  591.  */
  592. int
  593. readtab()
  594. {
  595.     struct stat st;
  596.  
  597.     /* If the file hasn't been opened, open it. */
  598.     if (bootfp == 0) {
  599.         if ((bootfp = fopen(bootptab, "r")) == NULLFILE) {
  600.             bp_log("Can't open bootptab file: %s\n", bootptab);
  601.             return (-1);
  602.         }
  603.     }
  604.  
  605.     /* Only reread if modified */
  606.     stat (bootptab, &st);
  607.     if (st.st_mtime == modtime && st.st_nlink) {
  608.         return (0); /* hasnt been modified or deleted yet */
  609.     }
  610.     /* It's been changed, reread. */
  611.  
  612.     if ((bootfp = fopen(bootptab, "r")) == NULLFILE) {
  613.         bp_log("Can't open %s\n", bootptab);
  614.         return (-1);
  615.     }
  616.     fstat(fileno(bootfp), &st);
  617.     bp_log("(re)reading %s\n", bootptab);
  618.     modtime = st.st_mtime;
  619.  
  620.     /*
  621.      * read and parse each line in the file.
  622.      */
  623.  
  624.     line = mallocw(BUFSIZ); 
  625.     
  626.     while (fgets(line, BUFSIZ, bootfp) != NULLCHAR) {
  627.         linenum++;
  628.  
  629.  
  630.         if ((line[0] == 0) || (line[0] == '#') || (line[0] == ' '))
  631.             continue;
  632.  
  633.         if (cmdparse (BootpdCmds, line, NULL) ==  -1)
  634.              continue;
  635.  
  636.     }
  637.     fclose(bootfp);
  638.     free (line);
  639.     return (0);
  640. }
  641.  
  642. void
  643. readtab_shut()
  644. {
  645.     modtime = 0;
  646. }
  647.  
  648. /*
  649.  * log an error message
  650.  *
  651.  */
  652. #if     defined(ANSIPROTO)
  653. void
  654. bp_log(char *fmt,...)
  655. {
  656.     FILE *fp;
  657.     va_list ap;
  658.  
  659.     if (LogOnScreen) {
  660.         va_start(ap,fmt);
  661.         vprintf(fmt, ap);
  662.         va_end(ap);
  663.         fflush (stdout);
  664.     }
  665.     if (LogInFile) {
  666.         if ((fp = fopen(bootplog, "a+")) == NULL) {
  667.             tprintf ("Cannot open bootplog.\n");
  668.             return;
  669.         }
  670.         va_start(ap,fmt);
  671.         vfprintf(fp, fmt, ap);
  672.         va_end(ap);
  673.         fflush(fp);
  674.         fclose(fp);
  675.     }
  676. }
  677. #else
  678. void
  679. bp_log(fmt, argv1, argv2, argv3, argv4, argv5, argv6, argv7, argv8, argv9, argv10)
  680. char *fmt;
  681. char *argv1;
  682. char *argv2;
  683. char *argv3;
  684. char *argv4;
  685. char *argv5;
  686. char *argv6;
  687. char *argv7;
  688. char *argv8;
  689. char *argv9;
  690. char *argv10;
  691. {
  692.     FILE *fp;
  693.  
  694.     if (LogOnScreen) {
  695.         printf(fmt, argv1, argv2, argv3, argv4, argv5, argv6, argv7,
  696.             argv8, argv9, argv10);
  697.         fflush (stdout);
  698.     }
  699.  
  700.     if (LogInFile) {
  701.         if ((fp = fopen(bootplog, "a+")) == NULL) {
  702.             tprintf ("Cannot open bootplog.\n");
  703.             return;
  704.         }
  705.         fprintf(fp, fmt, argv1, argv2, argv3, argv4, argv5, argv6, argv7,
  706.             argv8, argv9, argv10);
  707.         fflush (fp);
  708.         fclose(fp);
  709.     }
  710. }
  711. #endif
  712.